package com.lf.api.controller;

import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.servlet.ModelAndView;

import com.lf.api.Constants;
import com.lf.api.po.dao.TypeMapper;
import com.lf.api.po.domain.Subject;
import com.lf.api.po.domain.UserInfo;
import com.lf.api.service.SubjectService;
import com.lf.api.service.UserService;
import com.lf.api.util.IFConfig;
import com.lf.api.vo.MessageResult;
import com.lf.api.weixin.WeiXinUtil;
import com.lf.api.weixin.entity.SNSUserInfo;
import com.lf.api.weixin.entity.WeiXinAccount;
import com.lf.api.weixin.entity.WeixinOauth2Token;
import com.lf.common.util.CommonUtil;
import com.lf.common.util.UuidUtils;

/**
 * 
 * Description:  热门推荐/首页浏览列表/搜索列表/注册/登陆
 * Copyright: Copyright (c)2012
 * Company: Administrator
 * @author: Administrator
 * @version: 1.0
 * Create at: 2016年9月7日 下午11:26:43
 *
 * Modification History:
 * Date Author Version Description
 * ---------------------------修改历史---------------------------------------
 * 2016年9月7日 Administrator 1.0
 */
@Controller
public class IndexController {
	private static Logger log = LoggerFactory.getLogger(IndexController.class);
	@Autowired
	SubjectService subjectService;
	@Autowired
	TypeMapper typeMapper;
	@Autowired
	UserService userService;
	/**
	 * 
	 * Description:首页浏览列表页面
	 * Date:2016年9月7日
	 * @author Administrator
	 * @return MessageResult
	 */
	@RequestMapping("/subject/list/page")
	public String toIndex(HttpSession session, String code, String state){
		processOATH2(session, code);
		return "subject_list";
	}

	private void processOATH2(HttpSession session, String code) {
		if(StringUtils.isNotEmpty(code)){
			WeixinOauth2Token o2Token = WeiXinUtil.getOauth2AccessToken(WeiXinAccount.TEST.getAppID(), WeiXinAccount.TEST.getAppsecret(), code);
			log.info(o2Token.toString());
			if(null != o2Token && StringUtils.isNotEmpty(o2Token.getAccessToken()) 
					&& StringUtils.isNotEmpty(o2Token.getOpenId())){
				SNSUserInfo snsUserInfo = WeiXinUtil.getSNSUserInfo(o2Token.getAccessToken(), o2Token.getOpenId());
				if(null != snsUserInfo){
					Map<String, Object> map = new HashMap<String, Object>();
					map.put("openId", snsUserInfo.getOpenId());
					List<UserInfo> userInfoList = userService.selectUser(map);
					UserInfo user = null;
					if(CollectionUtils.isEmpty(userInfoList)){
						user = new UserInfo();
						user.setBirthday(null);
						user.setIcon(snsUserInfo.getHeadImgUrl());
						user.setGender((short)snsUserInfo.getSex());
						user.setLocation(snsUserInfo.getCity());
						user.setNickName(snsUserInfo.getNickname());
						user.setOpenId(snsUserInfo.getOpenId());
						user.setLevel((short) 0);
						user.setSpreadCode(UuidUtils.compressedUuid());
						user.setState((short) 0);
						user.setFansNum(0);
						user.setFavoriteNum(0);
						user.setSubscribeNum(0);
						user.setSubjectNum(0);
						user.setCreateTime(new Date());
						user.setScore(100);
						user.setUsername("");
						user.setPassword("");
						user.setUserType((short)1);
						user.setSalt(CommonUtil.randomNumbers());
						userService.insertUser(user);
						
						log.info(" new UserInfo=" + user);
						
						userInfoList = userService.selectUser(map);
						user.setId(userInfoList.get(0).getId());
					}else{
						user = userInfoList.get(0);
						log.info(" exists UserInfo=" + user);
					}
					session.setAttribute(Constants.USER_LOGIN, user);
				}
			}
		}
	}
	
	/**
	 * 
	 * Description:热门推荐/首页浏览列表
	 * Date:2016年9月7日
	 * @author Administrator
	 * @return MessageResult
	 */
	@ResponseBody
	@RequestMapping("/subject/list/data")
	public MessageResult index(HttpSession session, @RequestParam(defaultValue="1") Integer pageNo){
		Map<String, Object> param = new HashMap<String, Object>();
		param.put("start", (pageNo - 1) * 20);
		param.put("limit", 1000);
		List<Subject> subjects = subjectService.listSubject(param);
		return MessageResult.SUCCESS.setData(subjects);
	}
	
	/**
	 * 
	 * Description:添加主题页面
	 * Date:2016年9月7日
	 * @author Administrator
	 * @return MessageResult
	 */
	@RequestMapping("/subject/form/page")
	public ModelAndView toSubjectForm(HttpSession session, String code, String state, 
			HttpServletRequest request){
		ModelAndView view = new ModelAndView();
		processOATH2(session, code);
		
		view.addObject("typeList", typeMapper.listType());
		view.setViewName("subject_form");
		setJSSdkProperty(request, view);
		return view;
	}
	
	/**
	 * 
	 * Description:添加主题页面
	 * Date:2016年9月7日
	 * @author Administrator
	 * @return MessageResult
	 */
	@RequestMapping("/subject/add")
	public String addSubject(HttpSession session, String code, String state, Subject subject){
		processOATH2(session, code);
		UserInfo user = (UserInfo) session.getAttribute(Constants.USER_LOGIN);
		if(null != user){
			subject.setUserId(user.getId());
			subjectService.insertSubject(subject);
		}
		return "redirect:/subject/list/page";
	}
	
	/**
	 * 
	 * Description: 分享详情页面
	 * Date:2016年10月2日
	 * @author 小小书童
	 * @return ModelAndView
	 */
	@RequestMapping("/subject/detail/{id}")
	public ModelAndView toSubjectDetail(HttpSession session, String code, String state, 
			HttpServletRequest request, @PathVariable Long id){
		Subject subject = subjectService.getSubjectById(id);
		ModelAndView view = new ModelAndView();
		processOATH2(session, code);
		subject.setAudioUrl(IFConfig.getValue("voice_url", "") + subject.getAudioUrl());
		view.addObject("subject", subject);
		setJSSdkProperty(request, view);
		view.setViewName("subject_detail");
		return view;
	}

	private void setJSSdkProperty(HttpServletRequest request, ModelAndView view) {
		//微信设置
		String url = request.getScheme()+"://"+ request.getServerName()+request.getRequestURI()+"?"+request.getQueryString();
		log.info("js-sdk reqeust_url=:" + url);
		WeiXinAccount account = WeiXinAccount.TEST;
		view.addObject("appId", account.getAppID());
		long timestamp = System.currentTimeMillis() / 1000;
		view.addObject("timestamp", timestamp);
		String nonceStr = RandomStringUtils.random(16, true, true);
		view.addObject("nonceStr", nonceStr);
		String ticket = WeiXinUtil.getJSTicket(WeiXinUtil.getAccessToken(account).getAccessToken()).getTicket();
		String signature = WeiXinUtil.countSignature(ticket, nonceStr, timestamp + "", url);
		log.info("ticket=" + ticket + ",nonceStr=" + nonceStr + ",timestamp=" + timestamp + ",url=" + url + ",signature=" + signature);
		view.addObject("signature", signature);
	}
	
	/**
	 * 
	 * Description:搜索列表
	 * Date:2016年9月7日
	 * @author Administrator
	 * @return MessageResult
	 */
	@RequestMapping("/index/search")
	public MessageResult search(HttpSession session){
		
		return MessageResult.SUCCESS;
	}
	
	/**
	 * 
	 * Description:注册 
	 * Date:2016年9月7日
	 * @author Administrator
	 * @return MessageResult
	 */
	@RequestMapping("/index/register")
	public MessageResult greate(HttpSession session){
		
		return MessageResult.SUCCESS;
	}
	
	/**
	 * 
	 * Description:登陆
	 * Date:2016年9月7日
	 * @author Administrator
	 * @return MessageResult
	 */
	@RequestMapping("/index/login")
	public MessageResult listSubcribe(HttpSession session){
		
		return MessageResult.SUCCESS;
	}
	
	/**
	 * 
	 * Description:上传文件
	 * Date:2016年9月7日
	 * @author Administrator
	 * @return MessageResult
	 */
	@RequestMapping("/toUpload")
	public String toUpload(HttpSession session){
		return "upload_test";
	}
	
	/**
	 * 
	 * Description:上传文件
	 * Date:2016年9月7日
	 * @author Administrator
	 * @return MessageResult
	 */
	@ResponseBody
	@RequestMapping("/upload")
	public MessageResult upload(HttpSession session, HttpServletRequest request) {
		// 创建一个通用的多部分解析器
		CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(
				request.getSession().getServletContext());
		// 判断 request 是否有文件上传,即多部分请求
		String filePath = null;
		if (multipartResolver.isMultipart(request)) {
			// 转换成多部分request
			MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;
			// 记录上传过程起始时的时间，用来计算上传时间
			int pre = (int) System.currentTimeMillis();
			MultipartFile file = multiRequest.getFile("file");
			if (file != null) {
				// 取得当前上传文件的文件名称
				String myFileName = file.getOriginalFilename();
				if (StringUtils.isNotEmpty(myFileName)) {
					DateTime datetime = new DateTime();
					log.info("Upload file at:" + datetime.toString("yyyy-MM-dd HH:mm:ss", Locale.CHINESE)
							+ ", fileName=" + myFileName);
					// 重命名上传后的文件名
					String fileName = UuidUtils.compressedUuid();
					String extName = myFileName.substring(myFileName.lastIndexOf("."));
					String path = File.separator + datetime.getYear() + File.separator + datetime.getMonthOfYear()
							+ File.separator;
					String basePath = IFConfig.getValue(Constants.VOICE_PATH, "");
					File baseDir = new File(basePath + path);
					if (!baseDir.exists()) {
						baseDir.mkdirs();
					}
					File desFile = new File(baseDir, fileName + extName);
					if (!desFile.exists()) {
						try {
							desFile.createNewFile();
						} catch (IOException e) {
							log.error("Create des file error: {}", e.getMessage());
							e.printStackTrace();
						}
					}
					try {
						file.transferTo(desFile);
					} catch (IllegalStateException | IOException e) {
						log.error("Save des file error: {}", e.getMessage());
						e.printStackTrace();
					}
					filePath = path + fileName + extName;
				}
			}
			// 记录上传该文件后的时间
			int finaltime = (int) System.currentTimeMillis();
			log.info("Upload file finished, last time={}s", (finaltime - pre) / 1000);
		}
		return MessageResult.SUCCESS.setData(filePath);
	}

	/**
	 * 异常处理
	 * 
	 * @param ex
	 * @param request
	 * @throws InterruptedException 
	 * @Description:
	 */
	@ResponseBody
	@ExceptionHandler(Exception.class)
	public MessageResult handleException(Exception ex, HttpServletRequest request, HttpServletResponse response) throws InterruptedException {
		StringBuffer sb = new StringBuffer();
		if (ex instanceof org.springframework.web.multipart.MaxUploadSizeExceededException) {
			sb.append("文件大小不应大于" + ((MaxUploadSizeExceededException) ex).getMaxUploadSize() / 1000 + "kb");
		} else {
			sb.append("上传异常！");
		}
		Thread.sleep(1*1000);
		log.info("Upload file failed, {}s", ex.getMessage());  
		return MessageResult.SYSTEM_ERROR.setData(sb.toString());
	}
	
	/**
	 * 
	 * Description:上传文件
	 * Date:2016年9月7日
	 * @author Administrator
	 * @return MessageResult
	 */
	@ResponseBody
	@RequestMapping("/firsttype")
	public MessageResult listType(HttpSession session, HttpServletRequest request) {
		return MessageResult.SUCCESS.setData(typeMapper.listType());
	}
	
	@ResponseBody
	@RequestMapping(value="/login",method=RequestMethod.POST)
	public MessageResult login(HttpSession session, String username, String password) {
		if(StringUtils.isEmpty(username) || StringUtils.isEmpty(password)){
			return MessageResult.SYSTEM_ERROR.setMsg("username or password is null!");
		}
		try {
			return userService.login(username, password);
		} catch (Exception e) {
			e.printStackTrace();
			return MessageResult.SYSTEM_ERROR.setMsg(e.getMessage());
		}
	}
	
	@ResponseBody
	@RequestMapping(value="/register",method=RequestMethod.POST)
	public MessageResult register(HttpSession session, UserInfo user) {
		try {
			return userService.register(user);
		} catch (Exception e) {
			e.printStackTrace();
			return MessageResult.SYSTEM_ERROR.setMsg(e.getMessage());
		}
	}
	
}
